/**
 * 
 */
package com.thinkgsp.jxc.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgsp.jxc.model.Inventory;
import com.thinkgsp.jxc.model.InventoryAdd;
import com.thinkgsp.jxc.model.Product;
import com.thinkgsp.jxc.model.ProductBatchNo;
import com.thinkgsp.jxc.model.ProductClassify;
import com.thinkgsp.jxc.persistence.InventoryMapper;
import com.thinkgsp.jxc.persistence.mybatis.PagingResult;
import com.thinkgsp.jxc.service.InventoryService;
import com.thinkgsp.jxc.service.ProductService;
import com.thinkgsp.jxc.service.ServiceException;
import com.thinkgsp.sys.model.SysAccountPeriod;

/**
 * 产品库存业务实现类
 * @author evan
 *
 */
@Service("invService")
@Transactional
public class InventoryServiceImpl extends GeneralServiceImpl implements
		InventoryService {

	@Autowired
	private InventoryMapper invMapper;
	@Autowired
	private ProductService productService;
	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#setInventoryMapper(com.thinkgsp.jxc.persistence.InventoryMapper)
	 */
	public void setInventoryMapper(InventoryMapper invMapper) {
		this.invMapper = invMapper;
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#getInventory(java.lang.Long)
	 */
	public Inventory getInventory(Long invId) {
		return invMapper.getInventory(invId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#getInventoryList(java.lang.Integer, java.lang.Integer, java.lang.Integer)
	 */
	public List<Inventory> getInventoryList(Integer year, Integer period) {
		return invMapper.getInventoryByDept(year, period);
	}
	
	public PagingResult<Inventory> getInventoryList(Integer year,
			Integer period, int start, int size) {
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("fyear", year);
		params.put("period", period);
		params.put("deptId", this.getCurrentUser().getLogonDept().getDeptId());
		RowBounds rows = new RowBounds(start, size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByDeptCount", 
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByDeptPaging", 
				params, rows);
	}

	/**
	 * 查询某一库房的所有产品库存
	 * @param year
	 * @param period
	 * @param invaddId
	 * @return
	 */
	public List<Inventory> getInventoryListByInvAdd(Integer year,Integer period,Integer invaddId) {
		return invMapper.getInventoryByInvAdd(year, period, invaddId);
	}
	
	
	public PagingResult<Inventory> getInventoryListByInvAdd(Integer year,
			Integer period, Integer invaddId, int start, int size) {
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("fyear", year);
		params.put("period", period);
		params.put("invAddId", invaddId);
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByInvAddCount", 
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByInvAddPaging", 
				params, rows);
	}
	public List<Inventory> getInventoryList(Integer year,Integer period,
			Integer classifyId) {
		ProductClassify pc = productService.getProductClassify(classifyId);
		List<Inventory> list = new ArrayList<Inventory>();
		loadInventoryList(list,year,period,pc);
		return list;
	}
	
	private void loadInventoryList(List<Inventory> list,Integer year,Integer period,ProductClassify pc) {
		List<Inventory> invs = invMapper.getInventoryByClassifyId(year, period, pc.getClassifyId());
		if(invs != null && invs.size() > 0) {
			list.addAll(invs);
		}
		for(ProductClassify child : pc.getChilds()) {
			loadInventoryList(list, year, period, child);
		}
	}

	public PagingResult<Inventory> getInventoryList(Integer year,
			Integer period, Integer classifyId, int start, int size) {
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("fyear", year);
		params.put("period", period);
		List<Integer> ids = new ArrayList<Integer>();
		ProductClassify parent = productService.getProductClassify(classifyId);
		foreachClassifyIds(parent, ids);
		params.put("classifyIds", ids);
		RowBounds rows = new RowBounds(start, size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByClassifyIdCount", 
				"com.thinkgsp.jxc.persistence.InventoryMapper.getInventoryByClassifyIdPaging", 
				params, rows);
	}
	
	private void foreachClassifyIds(ProductClassify parent,List<Integer> ids) {
		ids.add(parent.getClassifyId());
		for(ProductClassify child : parent.getChilds()) {
			if(child.getChilds() != null && child.getChilds().size() > 0) {
				foreachClassifyIds(child,ids);
			} else {
				ids.add(child.getClassifyId());
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#findInventory(java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Long)
	 */
	public Inventory findInventory(Integer year, Integer period,
			Integer productId, Integer invAddId, Long batchNoId) {
		return invMapper.findInventory(year, period, productId, invAddId, batchNoId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#searchInventory(java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.String)
	 */
	public List<Inventory> searchInventory(Integer year, Integer period,Integer invAddId, String val) {
		return invMapper.searchInventoryByInvAddId(year, period, invAddId, val);
	}

	public PagingResult<Inventory> searchInventory(Integer year,
			Integer period, Integer invAddId, String val, int start, int size) {
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("fyear", year);
		params.put("period", period);
		params.put("invAddId", invAddId);
		params.put("val", val);
		RowBounds rows = new RowBounds(start, size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.InventoryMapper.searchInventoryByInvAddIdCount", 
				"com.thinkgsp.jxc.persistence.InventoryMapper.searchInventoryByInvAddIdPaging", 
				params, rows);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#searchInventory(java.lang.Integer, java.lang.Integer, java.lang.String)
	 */
	public List<Inventory> searchInventory(Integer year, Integer period,
			String val) {
		return invMapper.searchInventory(year, period, val);
	}

	public PagingResult<Inventory> searchInventory(Integer year,
			Integer period, String val, int start, int size) {
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("fyear", year);
		params.put("period", period);
		params.put("val", val);
		RowBounds rows = new RowBounds(start, size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.InventoryMapper.searchInventoryCount", 
				"com.thinkgsp.jxc.persistence.InventoryMapper.searchInventoryPaging", 
				params, rows);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#InitProductInventory(com.thinkgsp.jxc.model.Product, com.thinkgsp.jxc.model.ProductBatchNo, com.thinkgsp.jxc.model.InventoryAdd)
	 */
	public Inventory InitProductInventory(Product product,
			ProductBatchNo batchNo, InventoryAdd invAdd) throws ServiceException {
		SysAccountPeriod period = periodMapper.getCurrentPeriod();
		Inventory exists = invMapper.findInventory(period.getFyear(), period.getPeriod(),
				product.getProductId(), invAdd.getId(), batchNo.getId());
		if(exists != null) {
			throw new ServiceException("您添加的产品已经存在!");
		}
		Inventory inv = new Inventory();
		inv.setInvAddId(invAdd.getId());
		inv.setProductId(product.getProductId());
		inv.setBatchNoId(batchNo.getId());
		inv.setFyear(period.getFyear());
		inv.setPeriod(period.getPeriod());
		inv.setProduct(product);
		inv.setInventoryAdd(invAdd);
		inv.setBatchNo(batchNo);
		
		if(product.getProductBusProperties() != null && 
				product.getProductBusProperties().getCostPrice() != null) {
			inv.setCostPrice(product.getProductBusProperties().getCostPrice());
		} else {
			inv.setCostPrice(BigDecimal.ZERO);
		}
		
		invMapper.insertInventory(inv);
		return inv;
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#deleteInventory(java.lang.Long)
	 */
	public void deleteInventory(Long invId) throws ServiceException {
		int cnt = invMapper.deleteInventory(invId);
		if(cnt == 0) {
			log.warn("库存Id:" + invId + " 删除失败!");
			throw new ServiceException("库存Id:" + invId + " 删除失败!");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#updateCostPrice(java.lang.Long)
	 */
	public void updateCostPrice(Long invId) {
		invMapper.updateCostPrice(invId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#updateState(java.lang.Long, java.lang.Integer)
	 */
	public void updateState(Long invId, Integer state) {
		invMapper.updateState(invId, state);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.InventoryService#periodEndForward(java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Integer)
	 */
	public void periodEndForward(Integer curYear, Integer curPeriod,
			Integer nextYear, Integer nextPeriod) {
		invMapper.periodEndForward(curYear, curPeriod, nextYear, nextPeriod);
	}

}
